/**
 * @file pt_vad.c
 * @brief 
 * @author yejiahao
 * @date 2024-06-21 06:03:07
 * 
 * @copyright Copyright (c) 2024 by 深圳市鹏天微智能科技有限公司, All Rights Reserved.
 */

#include "pt_vad.h"
#include "pt_pcm_utils.h"

#define PCM_MONO_OUTPUT_PATH   "D:/Project/0000/ctest/demo/vad/output_mono.pcm"

/* 
48000Hz 16bit 双声道

1s 数据量
48000 * 16bit * 2

1ms 数据量
48*2*2 = 192 bytes

usb 一帧 1ms, int16_t 双声道有效数据 96 帧, 单声道 48 帧
 */

/* vad state */
typedef enum {
    VAD_MUTE, /*!< 手动静音状态 */
    VAD_TALKING, /*!< 正在讲话 */
    VAD_PREMUTE, /*!< 没有讲话, 即将静音 */

    VAD_MAX
} vad_state_t;

/* human voice detect env */
typedef struct
{
    int pass_cnt; /*!< 已记录符合要求的个数 */
} pt_det_env_t;

typedef struct
{
    vad_state_t state;

    pt_det_env_t hv; /*!< human voice detect env */
    pt_det_env_t talk; /*!< talking detect env */
    uint32_t premute_cnt; /*!< 准备静音持续个数 */
} pt_vad_env_t;
static pt_vad_env_t vad = {0};

int mute_cnt = 0;

void pt_vad_peek_pcm(void *pcm, uint32_t len)
{
    int16_t *stereo_pcm = pcm;
    uint32_t stereo_frames = len >> 1; /*!< 双声道 int16_t 数据个数, 48 */

    int temp;
    for (int i = 0; i < stereo_frames; i++)
    {
        temp = (int16_t)(stereo_pcm[i] & 0xffff);
        switch (vad.state)
        {
        case VAD_MUTE:
            if (temp > HV_DET_PASS_VALUE)
            {
                vad.hv.pass_cnt++;
                if (vad.hv.pass_cnt >= HV_DET_WINDOWS_CNT)
                {
                    vad.hv.pass_cnt = 0;
                    vad.state = VAD_TALKING;
                    PT_LOGD("to talking\n");
                }
            }
            else
            {
                vad.hv.pass_cnt = 0;
            }
            stereo_pcm[i] = 0; /*!< mute */
            break;

        case VAD_TALKING:
            if (temp < TALK_OVER_DET_PASS_VALUE)
            {
                vad.talk.pass_cnt++;
                if (vad.talk.pass_cnt >= TALK_OVER_DET_WINDOWS_CNT)
                {
                    vad.talk.pass_cnt = 0;

                    vad.state = VAD_PREMUTE;
                    PT_LOGD("to premute\n");
                }
            }
            else
            {
                vad.talk.pass_cnt = 0;
            }
            break;

        case VAD_PREMUTE:
            if (temp > PREMUTE_PASS_VALUE)
            {
                vad.premute_cnt = 0;
                vad.state = VAD_TALKING;
                PT_LOGD("back to talking\n");
            }
            else
            {
                vad.premute_cnt++;
                if (vad.premute_cnt > PREMUTE_WINDOWS_CNT)
                {
                    vad.premute_cnt = 0;
                    vad.state = VAD_MUTE;
                    PT_LOGD("to mute\n");
                    mute_cnt++;
                }
            }
            break;

        default:
            break;
        }
    }
}


void pt_vad_test(uint8_t *pcm, uint32_t len)
{
    // int16_t *stereo_pcm = pcm;
    // uint32_t stereo_frames = len >> 1; /*!< 双声道 int16_t 数据个数, 48 */

    /* 打印测试 */
    // for (int i = 0; i < 20; i++)
    // {
    //     PT_LOG("%d ", stereo_pcm[i]);
    // }
    // PT_LOG("\n");

    /* 转单声道 */
    // uint32_t mono_frames = stereo_frames >> 1; /*!< 单声道 int16_t 个数 */
    // PT_LOGD("%d %d %d\n", len, stereo_frames, mono_frames);

    // int16_t *mono_pcm = malloc(mono_frames * sizeof(int16_t));
    // if (!mono_pcm)
    // {
    //     PT_LOGE("mono pcm is null!\n");
    //     return;
    // }
    // pt_stereo2mono(stereo_pcm, stereo_frames, mono_pcm, mono_frames);
    // pt_save_pcm(PCM_MONO_OUTPUT_PATH, mono_pcm, (mono_frames * sizeof(int16_t)));
    // if (mono_pcm)
    // {
    //     free(mono_pcm);
    // }

    // int test[] = {0,1, 2,3,4,5,6,7,8, 9};
    // for (int i = 0; i < 10; i++)
    // {
    //     if(!is_continuous(test[i]))
    //     {
    //         PT_LOGD("!continuous %d\n", test[i]);
    //         break;
    //     }
    // }
    
    // PT_LOGD("continuous\n");

    // 模拟 usb epin
    for (int i = 0; i < (len / 192); i++)
    {
        pt_vad_peek_pcm((pcm + (i * 192)), 192);
    }

    PT_LOGD("mute_cnt=%d\n", mute_cnt);
}